/*
 * Msg.cpp
 *
 *  Created on: 2013. 7. 22.
 *      Author: jjaehuny
 */

#include <Dispatcher/Static.h>
#include <Database/Static.h>
#include "ChannelServer.h"
#include "User.h"
#include "Static.h"

#include <map>
#include <vector>
#include <memory>

namespace CacheServer {

void Msg::SendRegistAck(ChannelServer * pChannelServer, uint32_t seq, LocationResult result, const char * strError)
{
	RegistAck ack;
	ack.seq = seq;
	ack.result = result;
	ack.strError = strError;
	pChannelServer->SendMsg(ack);
}

void Msg::SendUnRegistAck(ChannelServer * pChannelServer, uint32_t seq, LocationResult result, const char * strError)
{
	UnRegistAck ack;
	ack.seq = seq;
	ack.result = result;
	ack.strError = strError;
	pChannelServer->SendMsg(ack);
}

void Msg::SendChatAck(ChannelServer * pChannelServer, uint32_t sender_seq, uint32_t receiver_seq, LocationResult result)
{
	ChatAck ack;
	ack.sender_seq = sender_seq;
	ack.result = result;
	ack.receiver_seq = receiver_seq;
	pChannelServer->SendMsg(ack);
}

void Msg::SendKick(ChannelServer * pChannelServer, uint32_t kickUserSeq)
{
	KickUser kick;
	kick.seq = kickUserSeq;
	pChannelServer->SendMsg(kick);
}

void Msg::SendRecallAck(ChannelServer * pChannelServer, uint32_t sender_seq, uint32_t receiver_seq, LocationResult result)
{
	RecallAck ack;
	ack.sender_seq = sender_seq;
	ack.result = result;
	ack.receiver_seq = receiver_seq;
	pChannelServer->SendMsg(ack);
}

void Msg::SendSetMainCharaterInfoAck(ChannelServer * pChannelServer, uint32_t seq, int16_t result)
{
	SetMainCharacterInfoAck ack;
	ack.seq = seq;
	ack.result = result;
	pChannelServer->SendMsg(ack);
}

void Msg::SendGetMainCharaterInfoAck(ChannelServer * pChannelServer, uint32_t seq, int16_t result)
{
	GetMainCharacterInfoAck ack;
	ack.seq = seq;
	ack.result = result;
	pChannelServer->SendMsg(ack);
}

void Msg::SendGetMainCharaterInfoAck_V2(ChannelServer * pChannelServer, uint32_t seq, int16_t result)
{
	GetMainCharacterInfoAck_V2 ack;
	ack.seq = seq;
	ack.result = result;
	pChannelServer->SendMsg(ack);
}

void
Msg::OnRegistSyn(Dispatcher::Session* pSession, ::Network::Packet * pPacket )
{
	ChannelServer * pChannelServer = (ChannelServer *)pSession;
	RegistSyn syn;
	pPacket->Read(syn);
	LOG(DEV, "OnRegistSyn seq : ", syn.seq );

	int mod = syn.seq % s_Mode;
	MAP & clsMap = s_clsTreeVector[mod];
	MAP::iterator itr = clsMap.find(syn.seq);
	if (clsMap.end() != itr)
	{
		LOG(DEV, "OnRegistSyn User Exist seq : ", syn.seq );
		SendRegistAck(pChannelServer, syn.seq, LOCATION_FAIL, "User Exist");


		std::shared_ptr<User> clsuser = itr->second;
		SendKick(clsuser->GetChannelServer(), clsuser->GetSeq());
		return;
	}

	std::shared_ptr<User> clsuser = ::CacheServer::s_clsuserpool.Create();
	clsuser->SetChannelServer(pChannelServer);
	clsuser->SetSeq(syn.seq);

	clsMap[syn.seq] = clsuser;

	LOG(DEV, "OnRegistSyn seq : ", syn.seq, " Regist Success");
	SendRegistAck(pChannelServer, syn.seq, LOCATION_SUCCESS, "User Regist Success");
}

void
Msg::OnUnRegistSyn(Dispatcher::Session* pSession, ::Network::Packet * pPacket )
{
	ChannelServer * pchannelserver = (ChannelServer *)pSession;
	UnRegistSyn syn;
	pPacket->Read(syn);
	LOG(DEV, "OnUnRegistSyn seq : ", syn.seq);

	int mod = syn.seq % s_Mode;
	MAP & clsMap = s_clsTreeVector[mod];
	MAP::iterator itr = clsMap.find(syn.seq);

	// not found user
	if (clsMap.end() == itr)
	{
		LOG(DEV, "OnUnRegistSyn seq : ", syn.seq, " User Not Exist");
		SendUnRegistAck(pchannelserver, syn.seq, LOCATION_FAIL, "User Not Exist");
		return;
	}

	clsMap.erase(syn.seq);
	LOG(DEV, "OnUnRegistSyn seq : ", syn.seq, " UnRegist Success");
	SendUnRegistAck(pchannelserver, syn.seq, LOCATION_SUCCESS, "User UnRegist Success");

}

void Msg::Chat(Dispatcher::Session* pSession, ::Network::Packet * pPacket )
{
	ChannelServer * pchannelserver = (ChannelServer *)pSession;
	ChatSyn syn;
	pPacket->Read(syn);
	LOG(DEV, "Char sender_seq : ", syn.sender_seq, " receive_seq : ", syn.receiver_seq);

//	int mod = syn.receiver_seq % s_Mode;
//	MAP & clsMap = s_clsTreeVector[mod];
//	MAP::iterator itr = clsMap.find(syn.sender_seq);

	// not found user
//	if (clsMap.end() == itr)
//	{
//		LOG(DEV, "Char seq : ", syn.sender_seq, " User Not Exist");
//		SendChatAck(pchannelserver, syn.sender_seq, syn.receiver_seq, LOCATION_NOT_EXIST_USER);
//		return;
//	}

	int mod = syn.receiver_seq % s_Mode;
	MAP & clsTargetMap = s_clsTreeVector[mod];
	MAP::iterator targetItr = clsTargetMap.find(syn.receiver_seq);

	// not found user
	if (clsTargetMap.end() == targetItr)
	{
		LOG(DEV, "Char seq : ", syn.sender_seq, " User Not Exist");
		SendChatAck(pchannelserver, syn.sender_seq, syn.receiver_seq, LOCATION_NOT_EXIST_TARGET_USER);
		return;
	}

	std::shared_ptr<User> clsuser = ( * targetItr).second;
	LOG(DEV, "Char receiver_seq__ : ", clsuser->GetSeq());
	clsuser->GetChannelServer()->SendMsg(syn);
}

void Msg::Recall(Dispatcher::Session* pSession, ::Network::Packet * pPacket )
{
	ChannelServer * pchannelserver = (ChannelServer *)pSession;
	RecallSyn syn;
	pPacket->Read(syn);
	LOG(DEV, "Char seq : ", syn.sender_seq);

	int mod = syn.sender_seq % s_Mode;
	MAP & clsMap = s_clsTreeVector[mod];
	MAP::iterator itr = clsMap.find(syn.sender_seq);

	// not found user
	if (clsMap.end() == itr)
	{
		LOG(DEV, "Char seq : ", syn.sender_seq, " User Not Exist");
		SendRecallAck(pchannelserver, syn.sender_seq, syn.receiver_seq, LOCATION_NOT_EXIST_USER);
		return;
	}

	mod = syn.receiver_seq % s_Mode;
	MAP & clsTargetMap = s_clsTreeVector[mod];
	MAP::iterator targetItr = clsTargetMap.find(syn.receiver_seq);

	// not found user
	if (clsTargetMap.end() == targetItr)
	{
		LOG(DEV, "Char seq : ", syn.sender_seq, " User Not Exist");
		SendRecallAck(pchannelserver, syn.sender_seq, syn.receiver_seq, LOCATION_NOT_EXIST_TARGET_USER);
		return;
	}

	std::shared_ptr<User> clsuser = ( * targetItr).second;;
	clsuser->GetChannelServer()->SendMsg(syn);
}

void Msg::OnRecallAck(Dispatcher::Session* pSession, ::Network::Packet * pPacket )
{
	RecallAck ack;
	pPacket->Read(ack);
	LOG(DEV, "Char seq : ", ack.sender_seq);

	int mod = ack.receiver_seq % s_Mode;
	MAP & clsTargetMap = s_clsTreeVector[mod];
	MAP::iterator targetItr = clsTargetMap.find(ack.receiver_seq);

	// not found user
	if (clsTargetMap.end() == targetItr)
	{
		LOG(DEV, "Char seq : ", ack.receiver_seq, " User Not Exist");
		return;
	}

	std::shared_ptr<User> clsuser = ( * targetItr).second;;
	clsuser->GetChannelServer()->SendMsg(ack);
}

void Msg::Close(Dispatcher::Session* pSession, ::Network::Packet * pPacket )
{
	ChannelServer * pchannelserver = (ChannelServer *)pSession;

	auto value = s_clsTreeVector.begin();
	for (; value != s_clsTreeVector.end(); ++ value)
	{
		LOG(DEV, "Close vector iterator");
		MAP & clsMap = ( * value );
		auto TreeItr = clsMap.begin();
		for (; TreeItr != clsMap.end(); ++TreeItr)
		{
			LOG(DEV, "Close tree iterator");
			if (pchannelserver == (TreeItr->second)->GetChannelServer())
			{
				LOG(DEV, "Close erase user user seq : ", (TreeItr->second)->GetSeq());
				clsMap.erase(TreeItr);
			}
		}
	}

	LOG(DEV, "Close end");
}

void Msg::TradeItemSoldout(Dispatcher::Session* pSession, ::Network::Packet * pPacket)
{
	TradeItemSoldoutSyn syn;
	pPacket->Read(syn);
	LOG(DEV, "OnTradeItemSoldout seq : ", syn.seller_userseq );

	int mod = syn.seller_userseq % s_Mode;
	MAP & clsMap = s_clsTreeVector[mod];
	MAP::iterator itr = clsMap.find(syn.seller_userseq);
	if (clsMap.end() == itr)
	{
		LOG(DEV, "OnTradeItemSoldout Not Connect User seq : ", syn.seller_userseq );
		return;
	}

	std::shared_ptr<User> clsuser = ( * itr).second;
	clsuser->GetChannelServer()->SendMsg(syn);
}

void Msg::SetMainCharacterInfoSyn(Dispatcher::Session * pSession, ::Network::Packet * pPacket)
{
	ChannelServer * pchannelserver = (ChannelServer *)pSession;
	::SetMainCharacterInfoSyn syn;
	pPacket->Read(syn);
	LOG(DEV, "Char seq : ", syn.seq);

	int mod = syn.seq % s_Mode;
	MAP & clsMap = s_clsTreeVector[mod];
	MAP::iterator itr = clsMap.find(syn.seq);

	// not found user
	if (clsMap.end() == itr)
	{
		LOG(DEV, "Char seq : ", syn.seq, " User Not Exist");
		SendSetMainCharaterInfoAck(pchannelserver, syn.seq, -4);
		return;
	}

	auto charInfo = itr->second->GetMainCharacterInfo();

	charInfo->_level = syn.level;
	charInfo->_class = syn.class_type;
	charInfo->_head = syn.head;
	charInfo->_armor = syn.armor;
	charInfo->_weapon = syn.weapon;
	charInfo->_sideHand = syn.side_hand;
	charInfo->_effect = syn.effect;
	charInfo->_petTid = syn.pet_tid;

	charInfo->_profile_opened = syn.profile_opened;
	charInfo->_gender	= syn.gender;
	charInfo->_gender_open = syn.gender_open;
	charInfo->_birthday_open = syn.birthday_open;
	charInfo->_strBirthday = syn.strBirthday.c_str();


	SendSetMainCharaterInfoAck(pchannelserver, syn.seq, 1);
}

void Msg::GetMainCharacterInfoSyn(Dispatcher::Session * pSession, ::Network::Packet * pPacket)
{
	ChannelServer * pchannelserver = (ChannelServer *)pSession;
	::GetMainCharacterInfoSyn syn;
	pPacket->Read(syn);
	LOG(DEV, "Char seq : ", syn.seq);

	GetMainCharacterInfoAck ack;
	ack.seq = syn.seq;
	ack.target_seq = syn.target_seq;

	int mod = syn.target_seq % s_Mode;
	MAP & clsTargetMap = s_clsTreeVector[mod];
	MAP::iterator targetItr = clsTargetMap.find(syn.target_seq);

	// not found user
	if (clsTargetMap.end() == targetItr)
	{
		LOG(DEV, "Char seq : ", syn.target_seq, " User Not Exist");
		SendGetMainCharaterInfoAck(pchannelserver, ack.seq, LOCATION_NOT_EXIST_TARGET_USER);
		return;
	}

	auto charInfo = targetItr->second->GetMainCharacterInfo();
	ack.result = 1;
	ack.level = charInfo->_level;
	ack.class_type = charInfo->_class;
	ack.head = charInfo->_head;
	ack.armor = charInfo->_armor;
	ack.weapon = charInfo->_weapon;
	ack.side_hand = charInfo->_sideHand;
	ack.effect = charInfo->_effect;
	ack.pet_tid = charInfo->_petTid;

	pchannelserver->SendMsg(ack);
}

void Msg::GetMainCharacterInfoSyn_V2(Dispatcher::Session * pSession, ::Network::Packet * pPacket)
{
	ChannelServer * pchannelserver = (ChannelServer *)pSession;
	::GetMainCharacterInfoSyn_V2 syn;
	pPacket->Read(syn);
	LOG(DEV, "Char seq : ", syn.seq);

	GetMainCharacterInfoAck_V2 ack;
	ack.seq = syn.seq;
	ack.target_seq = syn.target_seq;

	int mod = syn.target_seq % s_Mode;
	MAP & clsTargetMap = s_clsTreeVector[mod];
	MAP::iterator targetItr = clsTargetMap.find(syn.target_seq);

	// not found user
	if (clsTargetMap.end() == targetItr)
	{
		LOG(DEV, "Char seq : ", syn.target_seq, " User Not Exist");
		SendGetMainCharaterInfoAck_V2(pchannelserver, ack.seq, LOCATION_NOT_EXIST_TARGET_USER);
		return;
	}

	auto charInfo = targetItr->second->GetMainCharacterInfo();
	ack.result = 1;
	ack.level = charInfo->_level;
	ack.class_type = charInfo->_class;
	ack.head = charInfo->_head;
	ack.armor = charInfo->_armor;
	ack.weapon = charInfo->_weapon;
	ack.side_hand = charInfo->_sideHand;
	ack.effect = charInfo->_effect;
	ack.pet_tid = charInfo->_petTid;

	// TODO 신규 내용을 추가하자.
	ack.profile_opened = charInfo->_profile_opened;
	ack.gender = charInfo->_gender;
	ack.gender_open = charInfo->_gender_open;
	ack.birthday_open = charInfo->_birthday_open;
	ack.strBirthday = charInfo->_strBirthday.c_str();

	pchannelserver->SendMsg(ack);
}

} /* namespace cacheserver */




